﻿using System;
using System.Linq;
using Consul;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;

namespace Service.Consul
{
    public static class AppBuilderExtensions
    {
        public static void RegisterConsul(this IApplicationBuilder app, IApplicationLifetime lifetime,
            ILoggerFactory loggerFactory)
        {
            var logger = loggerFactory.CreateLogger("Service.Consul.RegisterConsul");
            var serverEntityOption = app.ApplicationServices.GetRequiredService<IOptions<ServerEntity>>();
            var serverEntity = serverEntityOption.Value;

            var consulClient = new ConsulClient(x => x.Address = new Uri($"{serverEntity.Url}"));//请求注册的 Consul 地址
            var serverEntities = serverEntity.ServiceEntities;
            if (serverEntities.Any())
            {
                foreach (var serviceEntity in serverEntities)
                {
                    var httpCheck = new AgentServiceCheck();
                    var httpCheckConf = serviceEntity.HttpCheck;
                    if (httpCheckConf != null)
                    {
                        //服务启动多久后注册
                        httpCheck.DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(httpCheckConf.DeregisterCriticalServiceAfter);
                        //健康检查时间间隔，或者称为心跳间隔
                        httpCheck.Interval = TimeSpan.FromSeconds(httpCheckConf.Interval);
                        //健康检查地址
                        httpCheck.HTTP = httpCheckConf.CheckUrl;
                        //超时
                        httpCheck.Timeout = TimeSpan.FromSeconds(httpCheckConf.Timeout);
                    }
                    // Register service with consul
                    var registration = new AgentServiceRegistration()
                    {
                        Checks = new[] { httpCheck },
                        ID = $"{serverEntity.Name }-{serviceEntity.Address}:{serviceEntity.Port}",
                        Name = serverEntity.Name,
                        Address = serviceEntity.Address,
                        Port = serviceEntity.Port,
                        Tags = new[] { $"urlprefix-/{serverEntity.Name}" }//添加 urlprefix-/servicename 格式的 tag 标签，以便 Fabio 识别
                    };

                    consulClient.Agent.ServiceRegister(registration).Wait();//服务启动时注册，内部实现其实就是使用 Consul API 进行注册（HttpClient发起）       
                    logger.LogTrace($"Finish registering service Id  [{ registration.ID }] ");
                }
            }
            
            lifetime.ApplicationStopping.Register(() =>
            {
                if (serverEntities.Any())
                {
                    foreach (var serviceEntity in serverEntities)
                    {
                        var id = $"{serverEntity.Name}-{serviceEntity.Address}:{serviceEntity.Port}";
                        consulClient.Agent.ServiceDeregister(id).Wait();//服务停止时取消注册
                    }
                }
            });
        }
    }
}
